﻿/************************************************************************
 * author:漠然 2013年7月12日4:25:15
 * **********************************************************************/

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;

namespace Mrsoft.Common
{
    /// <summary>
    /// Http下载类
    /// </summary>
    public static class WebEngine
    {

        private static readonly Dictionary<string, IPAddress> _dns = new Dictionary<string, IPAddress>();

        public static string DownloadString(string url) {
            //DnsEndPoint dns = new DnsEndPoint();
            //将url补全
            url = !url.StartsWith("http://") ? string.Format("http://{0}", url) : url;
            return DownloadString(new Uri(url));
        }

        public static string DownloadString(Uri uri) {
            string result;
            var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try {
                var ip = GetIp(uri.DnsSafeHost);
                if (socket.LocalEndPoint == null)
                    socket.Connect(ip, uri.Port);
                using (var ns = new NetworkStream(socket)) {
                    ns.Write("GET {0} HTTP/1.1\r\nUser-agent:MrEngine/1.0\r\nHOST:{1}\r\n\r\n", uri.PathAndQuery, uri.Host);
                    using (var ms = new MemoryStream()) {
                        var encoding = ns.GetResponse(ms);
                        //Console.WriteLine(encoding.EncodingName);
                        result = encoding.GetString(ms.ToArray());
                    }
                }
            }
            catch (Exception ex) {
                result = ex.Message;
            }
            socket.Close();
            return result;
        }

        private static IPAddress GetIp(string host) {
            host = host.ToLower();
            IPAddress result;
            if (!_dns.TryGetValue(host, out result)) {
                try {
                    var addrList = Dns.GetHostAddresses(host);
                    result = addrList[0];
                    _dns.Add(host, result);
                    if (host.ToLower().EndsWith(".duapp.com")) {
                        new Config<string>("./common.cfg", "ip/duapp", "180.149.131,99").Value = result.ToString();
                    }
                }
                catch (Exception ex) {
                    Mrsoft.Log.Write(ex.Message, LogLevel.错误);
                    if (!host.ToLower().EndsWith(".duapp.com")
                        && !IPAddress.TryParse(new Config<string>("./common.cfg", "ip/duapp", "180.149.131,99").Value, out result)) {
                        throw new Exception("dns解析失败");
                    }
                    _dns.Add(host, result);
                }
            }
            return result;
        }

        public static byte[] DownloadData(string url) {
            return DownloadData(new Uri(url));
        }

        public static byte[] DownloadData(Uri uri) {
            byte[] result;
            var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try {
                socket.Connect(GetIp(uri.DnsSafeHost), uri.Port);
                using (var ns = new NetworkStream(socket)) {
                    ns.Write("GET {0} HTTP/1.1\r\nUser-agent:MrEngine/1.0\r\nHOST:{1}\r\n\r\n", uri.PathAndQuery, uri.Host);
                    using (var ms = new MemoryStream()) {
                        ns.GetResponse(ms);
                        result = ms.ToArray();
                    }
                }
            }
            catch {
                result = null;
            }
            socket.Close();
            return result;
        }

        public static bool DownloadFile(string url, string fileName) {
            return DownloadFile(new Uri(url), fileName);
        }

        public static bool DownloadFile(Uri uri, string fileName) {
            var result = false;
            var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try {
                socket.Connect(GetIp(uri.DnsSafeHost), uri.Port);
                using (var ns = new NetworkStream(socket)) {
                    ns.Write("GET {0} HTTP/1.1\r\nUser-agent:MrEngine/1.0\r\nHOST:{1}\r\n\r\n", uri.PathAndQuery, uri.Host);
                    using (var fs = File.Create(fileName)) {
                        ns.GetResponse(fs);
                        fs.Close();
                    }
                }
                result = true;
            }
            catch //(Exception ex)
            {
                //Console.WriteLine();
            }
            socket.Close();
            return result;
        }

    }
}
